<?php
	
	namespace Aspic\Form\Element;
	use Aspic as A;
	use Aspic\Security\Security as S;
	
	/**
	* All DataElement are one value in $_POST array.
	* To have multiple values (and therefore multiple elments), you have to extends Container class.
	* So the value of the element will always be found $_REQUEST[$elementName]
	*/
	abstract class AbstractDataElement extends BasicElement implements DataElementInterface {
		use MappableElementTrait;
		
		/**
		* @var string The name of the data element (attribute "name")
		*/
		protected $_name;
		
		/**
		* @var bool If this is set to false the value of the element will not be set in the array return by top container with getValues() method
		 * Could be used to avoid some element to return value
		*/
		protected $_returnValue;
		
		/**
		 *
		 * @var string Object notation that link the element with its position in the form 
		 * retreieveValues array
		 */
		protected $mappedTo;
		
		public function __construct($name, array $options = array(), array $attributes = array()) {
			parent::__construct($options, $attributes);
			
			$this->opt('name', $name);
			$this->opt('returnValue', true, true);
			
		}
		
		/**
		 * Return the (full) name of the element
		 * @param boolean $abs If true, prefix the name of the element with parent form prefix
		 * @return string
		 */
		public function getName($abs = false) {
			if ($abs) {
				$nameKeys = A\UArray::getArrayKeysFromHtmlPath($this->opt('name'));
				$parentFormNamePrefix = explode('.', $this->getParentForm()->opt('namePrefix'));
				
				$merge = array_merge($parentFormNamePrefix, $nameKeys);
				
				$res = A\UArray::getHtmlPathFromArrayKeys($merge);
				
				return $res;
			}
			else {
				return $this->opt('name');
			}
		}
		
		public function getNameAttributeStr() {
			return 'name="'.S::escape($this->getName(true)).'"';
		}
		
		/**
		* Return the html attribute string for the element attribute + it's name (getNameAttributeStr)
		*/
		public function getAttrsAndNameStr() {
			if($this->isDuplicable) {
				$dynamicAttr = $this->attributes;
			
				$dynamicAttr['name'] = $this->getName(); // Add the dynamic name
				$dynamicAttr['id'] = $this->getDynamicId(); // Change the id
				
				return A\UString::implodeHtmlAttributes($dynamicAttr);
			}
			else {
				$attrs = $this->attributes;
				$attrs['name'] = $this->getName(true);
				
				return A\UString::implodeHtmlAttributes($attrs);				
			}
		}
		
		/**
		* Return the value of the element directly takes from PHP $_REQUEST array (no php modifications have been made on the value)
		*
		* @return mixed Return the value or null if it does not exists
		*/
		public function getHttpValue(array $form = null) {
			$form = static::getFormArray($form);

			$value = &A\UArray::getSubArrayRefFromHtmlPath($form, $this->getName(true));

			return $value;
		}
		
		/**
		* Return the value of the element THAT COULD BE MODIFIED by the element itself to return a "usable" value.
		* By default, this is the same as getHttpValue()
		*/
		public function getValue(array $form = null) {
			return $this->getHttpValue($form);
		}
		
		public function bind(array $formData = null) {
			return null;
		}
		
		/**
		* Return a JQuery selector to the element
		*/
		public function getElementSelector() {
			$selector = '[name="'.S::escapeJs($this->getName(true)).'"]';
			
			return $selector;
		}
		
		/**
		 * @return string|null
		 */
		public function getMappedTo($abs = false, $useElNameWhenNotMapped = true) {
			$mappedTo = $this->opt('mappedTo');
			
			$res = $mappedTo;
			
			if ($mappedTo == null AND $useElNameWhenNotMapped) {
				$name = $this->getName();
				
				$res = A\UString::getObjectNotationFromHtmlPath($name);
			}
			
			return $res;
		}
		
	}
	
?>